using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Audit
{
    /// <summary>
    /// 增强的审计上下文
    /// 提供完整的请求上下文信息收集和管理功能
    /// </summary>
    public class EnhancedAuditContext
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly ILogger<EnhancedAuditContext> _logger;
        private readonly Stopwatch _stopwatch;
        
        public string? CorrelationId { get; private set; }
        public string? TenantId { get; private set; }
        public string? UserId { get; private set; }
        public string? UserName { get; private set; }
        public string? IpAddress { get; private set; }
        public string? UserAgent { get; private set; }
        public string? HttpMethod { get; private set; }
        public string? RequestPath { get; private set; }
        public int? StatusCode { get; set; }
        public string? PermissionCode { get; set; }
        public DateTime StartTime { get; private set; }
        public long? Duration => _stopwatch?.ElapsedMilliseconds;

        public EnhancedAuditContext(IHttpContextAccessor httpContextAccessor, ILogger<EnhancedAuditContext> logger)
        {
            _httpContextAccessor = httpContextAccessor;
            _logger = logger;
            _stopwatch = new Stopwatch();
            StartTime = DateTime.UtcNow;
            
            InitializeFromHttpContext();
            _stopwatch.Start();
        }

        /// <summary>
        /// 从HTTP上下文初始化审计信息
        /// </summary>
        private void InitializeFromHttpContext()
        {
            var httpContext = _httpContextAccessor.HttpContext;
            if (httpContext == null) return;

            try
            {
                // 获取或生成 CorrelationId
                CorrelationId = httpContext.TraceIdentifier;
                if (httpContext.Request.Headers.TryGetValue("X-Correlation-ID", out var correlationHeader))
                {
                    CorrelationId = correlationHeader.FirstOrDefault();
                }
                
                // 获取租户信息
                if (httpContext.Request.Headers.TryGetValue("X-Tenant-ID", out var tenantHeader))
                {
                    TenantId = tenantHeader.FirstOrDefault();
                }
                
                // 从Claims或Session获取租户信息
                if (string.IsNullOrEmpty(TenantId) && httpContext.User.Identity?.IsAuthenticated == true)
                {
                    TenantId = httpContext.User.FindFirst("TenantId")?.Value ??
                               httpContext.User.FindFirst("tenant_id")?.Value;
                }
                
                // 获取用户信息
                if (httpContext.User.Identity?.IsAuthenticated == true)
                {
                    UserId = httpContext.User.FindFirst("sub")?.Value ??
                             httpContext.User.FindFirst("id")?.Value ??
                             httpContext.User.FindFirst("user_id")?.Value;
                             
                    UserName = httpContext.User.FindFirst("name")?.Value ??
                               httpContext.User.Identity.Name;
                }
                
                // 获取IP地址
                IpAddress = GetClientIpAddress(httpContext);
                
                // 获取User-Agent
                UserAgent = httpContext.Request.Headers["User-Agent"].FirstOrDefault();
                
                // 获取HTTP方法和路径
                HttpMethod = httpContext.Request.Method;
                RequestPath = httpContext.Request.Path.Value;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to initialize audit context from HTTP context");
            }
        }

        /// <summary>
        /// 获取客户端真实IP地址
        /// </summary>
        private string? GetClientIpAddress(HttpContext context)
        {
            try
            {
                // 尝试从代理头获取真实IP
                var xForwardedFor = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
                if (!string.IsNullOrEmpty(xForwardedFor))
                {
                    var ips = xForwardedFor.Split(',', StringSplitOptions.RemoveEmptyEntries);
                    if (ips.Length > 0)
                    {
                        return ips[0].Trim();
                    }
                }
                
                var xRealIp = context.Request.Headers["X-Real-IP"].FirstOrDefault();
                if (!string.IsNullOrEmpty(xRealIp))
                {
                    return xRealIp;
                }
                
                // 返回连接的远程IP
                return context.Connection.RemoteIpAddress?.ToString();
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to get client IP address");
                return null;
            }
        }

        /// <summary>
        /// 停止计时器
        /// </summary>
        public void Stop()
        {
            _stopwatch?.Stop();
        }

        /// <summary>
        /// 设置权限代码
        /// </summary>
        public void SetPermissionCode(string permissionCode)
        {
            PermissionCode = permissionCode;
        }

        /// <summary>
        /// 设置状态码
        /// </summary>
        public void SetStatusCode(int statusCode)
        {
            StatusCode = statusCode;
        }

        /// <summary>
        /// 设置租户ID
        /// </summary>
        public void SetTenantId(string tenantId)
        {
            TenantId = tenantId;
        }

        /// <summary>
        /// 从审计上下文创建审计日志条目
        /// </summary>
        public Domain.Entities.AuditLog CreateAuditLog(
            string type,
            string content,
            string result,
            string resource,
            string? exception = null,
            string? extendedData = null)
        {
            return new Domain.Entities.AuditLog
            {
                Type = type,
                Content = content,
                UserId = UserId ?? string.Empty,
                UserName = UserName ?? string.Empty,
                Timestamp = DateTime.UtcNow,
                IP = IpAddress ?? string.Empty,
                Result = result,
                Exception = exception ?? string.Empty,
                Resource = resource,
                TenantId = TenantId ?? string.Empty,
                UserAgent = UserAgent ?? string.Empty,
                Duration = Duration,
                CorrelationId = CorrelationId ?? string.Empty,
                HttpMethod = HttpMethod,
                RequestPath = RequestPath,
                StatusCode = StatusCode,
                PermissionCode = PermissionCode,
                ExtendedData = extendedData
            };
        }

        /// <summary>
        /// 创建403权限拒绝的审计日志
        /// </summary>
        public Domain.Entities.AuditLog CreatePermissionDeniedLog(
            string resource,
            string requiredPermission,
            string? additionalInfo = null)
        {
            var extendedData = System.Text.Json.JsonSerializer.Serialize(new
            {
                RequiredPermission = requiredPermission,
                RequestedResource = resource,
                AdditionalInfo = additionalInfo,
                RequestHeaders = _httpContextAccessor.HttpContext?.Request.Headers
                    .Where(h => !h.Key.StartsWith("Authorization"))
                    .ToDictionary(h => h.Key, h => h.Value.ToString())
            });

            return CreateAuditLog(
                type: "PermissionDenied",
                content: $"Access denied to resource '{resource}'. Required permission: '{requiredPermission}'",
                result: "Denied",
                resource: resource,
                extendedData: extendedData
            );
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _stopwatch?.Stop();
        }
    }
}
